#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <strings.h>
#include <ctype.h>

int main(int argc ,char *argv[]){

    // 参数
    if (argc < 2){
        fprintf(stderr, "Usgae argv ... \n");
        exit(-1);
    }

    // 监听文件描述符
    int lfd = socket(PF_INET, SOCK_STREAM, 0);
    if(lfd < 0){
        fprintf(stderr, "socket error \n");
        exit(-1);
    } 

    // 绑定端口号
    struct sockaddr_in ser_addr;
    bzero(&ser_addr,sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(atoi(argv[1]));
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if( bind(lfd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0 ){
        fprintf(stderr, "bind error \n");
        exit(-1);
    }

    // 监听
    if( listen(lfd,128) < 0 ){
        fprintf(stderr, "listen error \n");
        exit(-1);
    }

    // epoll根
    int epfd = epoll_create(1);
    // 上epoll树
    struct epoll_event event, *revent;
    revent = malloc(sizeof(struct epoll_event));
    event.data.fd = lfd;
    event.events = EPOLLIN;
    epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &event);
    int maxfd = lfd;
    int nready;

    // client
    struct sockaddr_in cli_addr;
    socklen_t cli_len = sizeof(cli_addr);
    bzero(&cli_addr, cli_len);
    char buf[1024];
    int n;
    // 通信
    while (1){
        nready = epoll_wait(epfd, revent, maxfd + 1, -1);
        if(nready == -1){
            fprintf(stderr, "epoll_wait error \n");
            exit(-1);
        }
        fputs("wait ... \n", stdout);

        for (size_t i = 0; i < nready; i++){
            // 连接请求
            if (revent[i].data.fd == lfd){
                int cfd = accept(lfd, (struct sockaddr *)&cli_addr, &cli_len);
                if(cfd < 0){
                    fprintf(stderr, "accept error \n");
                    exit(-1);
                }
                printf("client is ip=[%s] port=[%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
                event.data.fd = cfd;
                event.events = EPOLLIN | EPOLLET;
                epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &event);
                if(maxfd < cfd){
                    maxfd = cfd;
                }    
            }else{
                // 数据请求
                memset(buf, '\0', sizeof(buf));
                n = read(revent[i].data.fd, buf, 1);
                if(n == 0){
                    epoll_ctl(epfd, EPOLL_CTL_DEL, revent[i].data.fd, &event);
                    close(revent[i].data.fd);
                    printf("close client\n");
                }else{
                    printf("Get message from client: [%d] %s\n", n, buf);
                    for (size_t i = 0; i < n; i++){
                        buf[i] = toupper(buf[i]);
                    }
                    write(revent[i].data.fd, buf, n);
                }  
            }

        }
          
    }
    
    close(epfd);
    close(lfd);
    return 0;
}